﻿using System;
using System.Collections.Generic;
using System.IO;

namespace UnrarService
{
    public class DirectoryWatcher
    {
        #region Member
        private SortedList<String, FileType> _currentArchiveListe;
        private string _destinationPath;
        private Entpacker _rarEntpacker;
        #endregion

        #region Properties
        /// <summary>
        /// Der Zielpfad in den die Dateien entpackt werden sollen.
        /// </summary>
        public string DestinationPath
        {
            get { return _destinationPath; }
            set { _destinationPath = value; }
        }

        /// <summary>
        /// Die aktuelle ArchivListe, in der alle Archive enthalten sind.
        /// </summary>
        public SortedList<string, FileType> CurrentArchiveListe
        {
            get { return _currentArchiveListe; }
            set { _currentArchiveListe = value; }
        }

        /// <summary>
        /// Die Klasse zum Entpacken der Rar Dateien.
        /// </summary>
        public Entpacker RarEntpacker
        {
            get { return _rarEntpacker; }
            set { _rarEntpacker = value; }
        }
        #endregion

        #region Konstruktor
        /// <summary>
        /// Initialisieren des Directory Watchers, welcher die Dateien entpackt wenn diese vollständig geladen wurden.
        /// </summary>
        /// <param name="destinationPath">Der Zielpfad wohin die Dateien entpackt werden sollen</param>
        /// <param name="password">Die Passwortliste die überprüft werden soll beim Entpacken</param>
        public DirectoryWatcher(string destinationPath, List<string> password)
        {
            CurrentArchiveListe = new SortedList<string, FileType>();
            _destinationPath = destinationPath;
            _rarEntpacker = new Entpacker(destinationPath);
            _rarEntpacker.Password = password;
        }
        #endregion

        #region Functions/Subs
        /// <summary>
        /// Starten des FileWatchers
        /// </summary>
        /// <param name="filePath">Angeben des Pfades auf den gehorcht werden soll mit dem FileWatcher</param>
        public void StartWatcher(string filePath)
        {
            try
            {
                FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(filePath);
                //Der Filter geht nur auf einen Dateityp, wenn man mehrere prüfen will, muss man mehrere Watcher erstellen oder selbst den Dateityp prüfen den man bearbeiten will
                //fileSystemWatcher.Filter = "*.rar";
                fileSystemWatcher.Created += FileSystemWatcherCreated;
                fileSystemWatcher.Changed += FileSystemWatcherChanged;
                fileSystemWatcher.Renamed += FileSystemWatcherChanged;
                //Den Watcher aktivieren
                fileSystemWatcher.EnableRaisingEvents = true;
            }
            catch (Exception exception)
            {
                SQDebugging.Debugging.WriteLog(exception);
            }
        }

        /// <summary>
        /// Prüft den Dateityp, ob es sich um eine Datei handelt die entpackt werden soll, dabei werden auch Dateien mit der Endung "*.rar.html" behandelt.
        /// </summary>
        /// <param name="fullPath">komplette Dateipfad</param>
        /// <returns>TRUE -> Entpacken | False -> nicht entpacken</returns>
        private bool CheckFileType(string fullPath)
        {
            //TODO bei Problemen evtl. noch prüfen ob es sich auch um eine Datei handelt und nicht um einen Ordner

            if (fullPath != null)
            {
                //Wenn es sich um eine Rarfile handelt, dann wird diese Datei entpackt
                if (String.Compare(Path.GetExtension(fullPath).Trim('.'), "rar", true) == 0)
                {
                    return true;
                }

                //Prüft ob es sich um einen Dateinamen handelt der am Ende auf HTML endet aber trotzdem "rar" enthält, diese kann trotzdem entpakt werden.
                if (String.Compare(Path.GetExtension(fullPath).Trim('.'), "html", true) == 0 && Path.GetFileNameWithoutExtension(fullPath).ToLower().EndsWith("rar"))
                {
                    return true;
                }
            }

            return false;
        }
        #endregion

        #region Events
        /// <summary>
        /// Bemerkt die Statusänderungen von Dateien, d.h. wenn diese angelegt werden bzw. wenn diese fertig heruntergeladen wurden.
        /// </summary>
        void FileSystemWatcherChanged(object sender, FileSystemEventArgs e)
        {
            //Als erstes ! Prüfen ob es sich um einen Dateityp handelt den wir entpacken wollen.
            if (CheckFileType(e.FullPath))
            {
                //Prüfen ob auf die Datei zugegriffen werden kann
                if (!SQSystem.FileAccessCheck.IsFileInUse(e.FullPath))
                {
                    string fileNameWithoutExtensions = FileType.ClearFileName(e.Name);

                    if (CurrentArchiveListe.ContainsKey(fileNameWithoutExtensions))
                    {
                        //Die File sollte sich auf jedenfall in dieser Auflistung befinden, denn sie muss schon beim Created Event hinzugefügt worden sein.
                        if (CurrentArchiveListe.ContainsKey(fileNameWithoutExtensions))
                        {
                            CurrentArchiveListe[fileNameWithoutExtensions].AddFileName(e.FullPath, true);
                        }

                        //Prüfen ob das Packet entpackt werden soll
                        if ((CurrentArchiveListe.ContainsKey(fileNameWithoutExtensions) && CurrentArchiveListe[fileNameWithoutExtensions].CheckEntpackStatus()))
                        {
                            if (_rarEntpacker.Entpacken(CurrentArchiveListe[fileNameWithoutExtensions].FirstArchiveFilePath))
                            {
                                //Löschen der Rar Archive von der Festplatte nach einem erfolgreichen entpacken.
                                CurrentArchiveListe[fileNameWithoutExtensions].DeleteRarFiles();
                            }
                            CurrentArchiveListe.Remove(fileNameWithoutExtensions);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Merkt nur wenn eine Datei neu angelegt wird.
        /// </summary>
        void FileSystemWatcherCreated(object sender, FileSystemEventArgs e)
        {
            string fileNameWithoutExtensions = FileType.ClearFileName(e.Name);

            //Prüfen ob es sich hier bei der neu angelegten File auch um eine Datei handelt die wir entpacken sollen.
            if (CheckFileType(e.FullPath))
            {
                //Erst einmal nur die Dateien zur Liste hinzufügen, die dem Verzeichnis neu hinzugefügt wurden.
                if (!CurrentArchiveListe.ContainsKey(fileNameWithoutExtensions))
                {
                    CurrentArchiveListe.Add(fileNameWithoutExtensions, new FileType(e.FullPath));
                }
                else
                {
                    CurrentArchiveListe[fileNameWithoutExtensions].AddFileName(e.FullPath, false);
                }
            }
        }
        #endregion

    }
}
